﻿using System;
using System.Diagnostics.CodeAnalysis;
using System.Windows;

using YourLastOptionsDialog.ViewModels.Options;
using YourLastOptionsDialog.Views;

namespace YourLastOptionsDialog
{
    /// <summary>
    /// The default implementation of the <see cref="IOptionsViewFactory"/> interface that is used
    /// unless the user overrides it with an own or derived implementation.
    /// </summary>
    public class DefaultOptionsViewFactory : IOptionsViewFactory
    {
        #region Implementation of IOptionsViewFactory

        /// <summary>
        /// Creates the view for the given option.
        /// </summary>
        /// <param name="option">The option to create a view for.</param>
        /// <returns>A framework element that is able to edit the given option.</returns>
        [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily", Justification = "I accept this here to simplify the code.")]
        public virtual FrameworkElement CreateViewFor(Option option)
        {
            if (option == null)
            {
                throw new ArgumentNullException("option");
            }

            // simple if-else
            FrameworkElement result = null;
            if (option is BooleanOption)
            {
                result = new BooleanEditor();
            }
            else if (option is DateTimeOption)
            {
                var dateTimeEditor = new DateTimeEditor();
                dateTimeEditor.DateTimeMode = (option as DateTimeOption).Mode;
                result = dateTimeEditor;
            }
            else if (option is IntegralOptionBase)
            {
                var integralEditor = new NumericEditor();
                result = integralEditor;
            }
            else if (option is FloatOptionBase)
            {
                var floatEditor = new NumericEditor();
                result = floatEditor;
            }
            else if (option is PasswordOption)
            {
                // it's important to check for the password option before the string option,
                // because password option derives from string option
                var passwordEditor = new PasswordEditor();
                result = passwordEditor;
            }
            else if (option is StringOption)
            {
                var stringEditor = new StringEditor();
                stringEditor.InputScope = (option as StringOption).InputScope;
                result = stringEditor;
            }
            else if (option is EnumOption)
            {
                result = new EnumEditor();
            }

            if (result == null)
            {
                throw new ArgumentException("No editor available for an option of type " + option.GetType().Name);
            }

            result.DataContext = option;
            return result;
        }

        #endregion
    }
}